{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Errors\n",
    "\n",
    "- Author: [seofiled](https://github.com/seofield)\n",
    "- Peer Review: \n",
    "- Proofread : [hong-seongmin](https://github.com/hong-seongmin)\n",
    "- This is a part of [LangChain Open Tutorial](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial)\n",
    "\n",
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/17-LangGraph/01-Core-Features/16-LangGraph-Errors.ipynb)[![Open in GitHub](https://img.shields.io/badge/Open%20in%20GitHub-181717?style=flat-square&logo=github&logoColor=white)](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/17-LangGraph/01-Core-Features/16-LangGraph-Errors.ipynb)\n",
    "## Overview\n",
    "\n",
    "- Understanding common error types is crucial for building and maintaining robust graph-based workflows. \n",
    "- This tutorial introduces key LangGraph errors, demonstrates scenarios that trigger them, and guides you through resolving each error. \n",
    "- By intentionally causing these errors and troubleshooting them step-by-step, you’ll gain a practical understanding of LangGraph’s error-handling mechanisms.\n",
    "\n",
    "### Table of Contents\n",
    "\n",
    "- [Overview](#overview)\n",
    "- [GraphRecursionError](#graphrecursionerror)\n",
    "- [InvalidUpdateError](#invalidupdateerror)\n",
    "- [MultipleSubgraphsError](#multiplesubgraphserror)\n",
    "\n",
    "### References\n",
    "\n",
    "- [LangGraph API Reference: Errors](https://langchain-ai.github.io/langgraph/reference/errors/)\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment Setup\n",
    "\n",
    "Setting up your environment is the first step. See the [Environment Setup](https://wikidocs.net/257836) guide for more details.\n",
    "\n",
    "\n",
    "**[Note]**\n",
    "\n",
    "The langchain-opentutorial is a package of easy-to-use environment setup guidance, useful functions and utilities for tutorials.\n",
    "Check out the  [```langchain-opentutorial```](https://github.com/LangChain-OpenTutorial/langchain-opentutorial-pypi) for more details."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install langchain-opentutorial"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install required packages\n",
    "from langchain_opentutorial import package\n",
    "\n",
    "package.install(\n",
    "    [\n",
    "        \"langchain\",\n",
    "    ],\n",
    "    verbose=False,\n",
    "    upgrade=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GraphRecursionError\n",
    "- The ```GraphRecursionError``` error is raised when your LangGraph StateGraph exceeds the maximum number of steps during execution. \n",
    "- This safeguard prevents infinite loops caused by cyclic dependencies in your graph or overly complex graphs that naturally require many iterations.\n",
    "- Below is a case where the graph loops infinitely and never ends. In this case, an ```GraphRecursionError``` prevents the infinite loop.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---Node 1---\n",
      "---Node 2---\n",
      "---Node 1---\n",
      "---Node 2---\n",
      "---Node 1---\n",
      "---Node 2---\n",
      "---Node 1---\n",
      "---Node 2---\n",
      "---Node 1---\n",
      "---Node 2---\n",
      "GraphRecursionError occurred: Recursion limit of 10 reached without hitting a stop condition. You can increase the limit by setting the `recursion_limit` config key.\n",
      "For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/GRAPH_RECURSION_LIMIT\n"
     ]
    }
   ],
   "source": [
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.errors import GraphRecursionError\n",
    "from typing import TypedDict\n",
    "\n",
    "# Define the state structure for the graph\n",
    "class GraphState(TypedDict):\n",
    "    input: str\n",
    "\n",
    "# Define the first node\n",
    "def node_1(state: GraphState):\n",
    "    print(\"---Node 1---\")\n",
    "    return {\"input\": state[\"input\"]}\n",
    "\n",
    "# Define the second node\n",
    "def node_2(state: GraphState):\n",
    "    print(\"---Node 2---\")\n",
    "    return {\"input\": state[\"input\"]}\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(GraphState)\n",
    "builder.add_node(\"node_1\", node_1)\n",
    "builder.add_node(\"node_2\", node_2)\n",
    "\n",
    "# Define the edges between nodes\n",
    "builder.add_edge(START, \"node_1\")\n",
    "builder.add_edge(\"node_1\", \"node_2\")\n",
    "builder.add_edge(\"node_2\", \"node_1\")\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Execute the graph with a recursion limit to prevent infinite loops\n",
    "try:\n",
    "    graph.invoke({\"input\": \"test\"}, {\"recursion_limit\": 10})\n",
    "except GraphRecursionError as e:\n",
    "    print(f\"GraphRecursionError occurred: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If your graph is not an infinite loop and you set appropriate limits, it will work fine."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---Node 1---\n",
      "---Node 2---\n",
      "Execution succeeded: {'input': 'test'}\n"
     ]
    }
   ],
   "source": [
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.errors import GraphRecursionError\n",
    "from typing import TypedDict\n",
    "\n",
    "# Define the state structure for the graph\n",
    "class GraphState(TypedDict):\n",
    "    input: str\n",
    "\n",
    "# Define the first node\n",
    "def node_1(state: GraphState):\n",
    "    print(\"---Node 1---\")\n",
    "    return {\"input\": state[\"input\"]}\n",
    "\n",
    "# Define the second node\n",
    "def node_2(state: GraphState):\n",
    "    print(\"---Node 2---\")\n",
    "    return {\"input\": state[\"input\"]}\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(GraphState)\n",
    "builder.add_node(\"node_1\", node_1)\n",
    "builder.add_node(\"node_2\", node_2)\n",
    "\n",
    "# Define the edges between nodes\n",
    "builder.add_edge(START, \"node_1\")  # Start the graph execution with node_1\n",
    "builder.add_edge(\"node_1\", \"node_2\")  # Connect node_1 to node_2\n",
    "builder.add_edge(\"node_2\", END)  # Connect node_2 to the END node\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Execute the graph with a recursion limit\n",
    "try:\n",
    "    # Invoke the graph with initial state and recursion limit\n",
    "    result = graph.invoke({\"input\": \"test\"}, {\"recursion_limit\": 5})\n",
    "except GraphRecursionError as e:\n",
    "    print(f\"GraphRecursionError occurred: {e}\")\n",
    "print(f\"Execution succeeded: {result}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## InvalidUpdateError\n",
    "\n",
    "The ```InvalidUpdateError``` is an error that occurs when a channel is updated with an invalid or incompatible set of updates. This typically indicates a mismatch between the updates being applied and the expected format or behavior of the graph.\n",
    "\n",
    "### INVALID_CONCURRENT_GRAPH_UPDATE\n",
    "\n",
    "- This error is triggered when multiple nodes concurrently update the same state property in a StateGraph, and no mechanism exists to resolve these conflicts.\n",
    "- Parallel execution (e.g., fanout) causes multiple nodes to update the same state key.\n",
    "- LangGraph cannot determine how to merge these updates, resulting in the error.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "InvalidUpdateError: At key 'input': Can receive only one value per step. Use an Annotated key to handle multiple values.\n",
      "For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE\n"
     ]
    }
   ],
   "source": [
    "from langgraph.errors import InvalidUpdateError\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "from typing import TypedDict\n",
    "\n",
    "# Define the state structure for the graph\n",
    "class State(TypedDict):\n",
    "    input: str\n",
    "\n",
    "# Define the first node\n",
    "def node(state: State):\n",
    "    return {\"input\": \"value_from_node\"}\n",
    "\n",
    "# Define the second node\n",
    "def other_node(state: State):\n",
    "    return {\"input\": \"value_from_other_node\"}\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(State)\n",
    "builder.add_node(\"node\", node)\n",
    "builder.add_node(\"other_node\", other_node)\n",
    "\n",
    "# Set up parallel execution\n",
    "builder.add_edge(START, \"node\")  # Start execution with node\n",
    "builder.add_edge(START, \"other_node\")  # Start execution with other_node in parallel\n",
    "builder.add_edge(\"node\", END)\n",
    "builder.add_edge(\"other_node\", END)\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Execute the graph\n",
    "try:\n",
    "    graph.invoke({\"input\": \"\"})\n",
    "except InvalidUpdateError as e:\n",
    "    print(f\"InvalidUpdateError: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use a Reducer to Handle Conflicts\n",
    "\n",
    "- Reducers are essential for resolving conflicts when multiple nodes in a graph attempt to update the same state key during parallel execution. They define how to combine these updates, ensuring smooth and conflict-free operation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Execution succeeded: {'input': ['value_from_node', 'value_from_other_node']}\n"
     ]
    }
   ],
   "source": [
    "import operator\n",
    "from typing import TypedDict, Annotated\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "\n",
    "# Define the state structure with a reducer\n",
    "class State(TypedDict):\n",
    "    # Use a reducer to merge updates by appending to the list\n",
    "    input: Annotated[list, operator.add]\n",
    "\n",
    "# Define the first node\n",
    "def node(state: State):\n",
    "    return {\"input\": [\"value_from_node\"]}\n",
    "\n",
    "# Define the second node\n",
    "def other_node(state: State):\n",
    "    return {\"input\": [\"value_from_other_node\"]}\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(State)\n",
    "builder.add_node(\"node\", node)\n",
    "builder.add_node(\"other_node\", other_node)\n",
    "\n",
    "# Set up parallel execution\n",
    "builder.add_edge(START, \"node\")  # Start execution with node\n",
    "builder.add_edge(START, \"other_node\")  # Start execution with other_node in parallel\n",
    "builder.add_edge(\"node\", END)\n",
    "builder.add_edge(\"other_node\", END)\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Execute the graph\n",
    "try:\n",
    "    result = graph.invoke({\"input\": []})\n",
    "except InvalidUpdateError as e:\n",
    "    print(f\"InvalidUpdateError: {e}\")\n",
    "print(\"Execution succeeded:\", result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### INVALID_GRAPH_NODE_RETURN_VALUE\n",
    "\n",
    "The ```INVALID_GRAPH_NODE_RETURN_VALUE``` error in LangGraph occurs when a node in a StateGraph returns a value that is not a dictionary. Every node in your graph must return a dictionary with one or more keys that match the defined state schema.\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "InvalidUpdateError: Expected dict, got ['bad_node']\n",
      "For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE\n"
     ]
    }
   ],
   "source": [
    "from typing import TypedDict\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.errors import InvalidUpdateError\n",
    "\n",
    "# Define the state structure for the graph\n",
    "class State(TypedDict):\n",
    "    input: str\n",
    "\n",
    "# Define a node with an invalid return type\n",
    "def bad_node(state: State):\n",
    "    # Incorrectly returns a list instead of a dictionary\n",
    "    return [\"bad_node\"]\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(State)\n",
    "builder.add_node(\"bad_node\", bad_node)\n",
    "\n",
    "# Set up the edges\n",
    "builder.add_edge(START, \"bad_node\")\n",
    "builder.add_edge(\"bad_node\", END)\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Execute the graph\n",
    "try:\n",
    "    graph.invoke({\"input\": \"test\"})\n",
    "except InvalidUpdateError as e:\n",
    "    print(f\"InvalidUpdateError: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ensure the Node Returns a Dictionary\n",
    "\n",
    "- Nodes must always return a dictionary matching the state schema."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Execution succeeded: {'input': 'test corrected'}\n"
     ]
    }
   ],
   "source": [
    "from typing import TypedDict\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "\n",
    "# Define the state structure for the graph\n",
    "class State(TypedDict):\n",
    "    input: str\n",
    "\n",
    "# Define a valid node\n",
    "def fixed_node(state: State):\n",
    "    # Returns a dictionary with the corrected input\n",
    "    return {\"input\": state[\"input\"] + \" corrected\"}\n",
    "\n",
    "# Build the graph\n",
    "builder = StateGraph(State)\n",
    "\n",
    "# Add the corrected node to the graph\n",
    "builder.add_node(\"fixed_node\", fixed_node)\n",
    "\n",
    "# Define the edges\n",
    "builder.add_edge(START, \"fixed_node\")\n",
    "builder.add_edge(\"fixed_node\", END)\n",
    "\n",
    "# Compile the graph\n",
    "graph = builder.compile()\n",
    "\n",
    "# Define the initial state\n",
    "initial_state = {\"input\": \"test\"}\n",
    "\n",
    "# Execute the graph\n",
    "try:\n",
    "    result = graph.invoke({\"input\": \"test\"})\n",
    "except InvalidUpdateError as e:\n",
    "    print(f\"InvalidUpdateError: {e}\")\n",
    "print(\"Execution succeeded:\", result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MultipleSubgraphsError\n",
    "\n",
    "The ```MultipleSubgraphsError``` occurs when multiple subgraphs are invoked within a single LangGraph node, particularly when checkpointing is enabled for each subgraph. This restriction exists due to how LangGraph handles checkpoint namespacing for subgraphs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MultipleSubgraphsError: Multiple subgraphs called inside the same node\n",
      "\n",
      "Troubleshooting URL: https://python.langchain.com/docs/troubleshooting/errors/MULTIPLE_SUBGRAPHS/\n"
     ]
    }
   ],
   "source": [
    "from langgraph.errors import MultipleSubgraphsError\n",
    "from typing import TypedDict\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "import uuid\n",
    "\n",
    "# Define the state structure for the subgraphs\n",
    "class SubGraphState(TypedDict):\n",
    "    value: int\n",
    "\n",
    "# Define the first subgraph node\n",
    "def subgraph_node_1(state: SubGraphState):\n",
    "    return {\"value\": state[\"value\"] + 1}\n",
    "\n",
    "# Define the second subgraph node\n",
    "def subgraph_node_2(state: SubGraphState):\n",
    "    return {\"value\": state[\"value\"] * 2}\n",
    "\n",
    "# Build the first subgraph\n",
    "subgraph_builder_1 = StateGraph(SubGraphState)\n",
    "subgraph_builder_1.add_node(\"subgraph_node_1\", subgraph_node_1)\n",
    "subgraph_builder_1.add_edge(START, \"subgraph_node_1\")\n",
    "subgraph_builder_1.add_edge(\"subgraph_node_1\", END)\n",
    "\n",
    "checkpointer_1 = MemorySaver()\n",
    "subgraph_1 = subgraph_builder_1.compile(checkpointer=checkpointer_1)\n",
    "\n",
    "# Build the second subgraph\n",
    "subgraph_builder_2 = StateGraph(SubGraphState)\n",
    "subgraph_builder_2.add_node(\"subgraph_node_2\", subgraph_node_2)\n",
    "subgraph_builder_2.add_edge(START, \"subgraph_node_2\")\n",
    "subgraph_builder_2.add_edge(\"subgraph_node_2\", END)\n",
    "\n",
    "checkpointer_2 = MemorySaver()\n",
    "subgraph_2 = subgraph_builder_2.compile(checkpointer=checkpointer_2)\n",
    "\n",
    "# Define the main graph state structure\n",
    "class MainGraphState(TypedDict):\n",
    "    value: int\n",
    "    result: int\n",
    "\n",
    "# Define the main graph node\n",
    "def main_node(state: MainGraphState):\n",
    "    # Call two subgraphs within a single node\n",
    "    subgraph_output_1 = subgraph_1.invoke({\"value\": state[\"value\"]})\n",
    "    subgraph_output_2 = subgraph_2.invoke({\"value\": state[\"value\"]})\n",
    "    return {\"result\": subgraph_output_1[\"value\"] + subgraph_output_2[\"value\"]}\n",
    "\n",
    "# Build the main graph\n",
    "main_builder = StateGraph(MainGraphState)\n",
    "main_builder.add_node(\"main_node\", main_node)\n",
    "main_builder.add_edge(START, \"main_node\")\n",
    "main_builder.add_edge(\"main_node\", END)\n",
    "\n",
    "main_checkpointer = MemorySaver()\n",
    "main_graph = main_builder.compile(checkpointer=main_checkpointer)\n",
    "\n",
    "# Configure and execute the graph\n",
    "config = {\n",
    "    \"configurable\": {\n",
    "        \"thread_id\": uuid.uuid4(),\n",
    "    }\n",
    "}\n",
    "\n",
    "try:\n",
    "    result = main_graph.invoke({\"value\": 5, \"result\": 0}, config)\n",
    "    \n",
    "except MultipleSubgraphsError as e:\n",
    "    print(f\"MultipleSubgraphsError: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Disable Checkpointing for Subgraphs\n",
    "\n",
    "- If you do not need to interrupt or resume the subgraphs, disable checkpointing by compiling them with checkpointer=False:\n",
    "- Best Practices for Avoiding ```MultipleSubgraphsError```\n",
    "  1.\tPlan Subgraph Execution: Avoid invoking multiple subgraphs imperatively within a single node. Use modular design with separate nodes.\n",
    "  2.\tUse Checkpointers Judiciously: Only enable checkpointing for subgraphs where interruption and resumption are critical.\n",
    "  3.\tDebug Graph Logic: Visualize your graph or use debugging tools to understand where subgraph calls are being made."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Execution succeeded: {'value': 5, 'result': 16}\n"
     ]
    }
   ],
   "source": [
    "from typing import TypedDict\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "import uuid\n",
    "\n",
    "# Define the state structure for the subgraphs\n",
    "class SubGraphState(TypedDict):\n",
    "    value: int\n",
    "\n",
    "# Define the first subgraph node\n",
    "def subgraph_node_1(state: SubGraphState):\n",
    "    return {\"value\": state[\"value\"] + 1}\n",
    "\n",
    "# Define the second subgraph node\n",
    "def subgraph_node_2(state: SubGraphState):\n",
    "    return {\"value\": state[\"value\"] * 2}\n",
    "\n",
    "# Build the first subgraph\n",
    "subgraph_builder_1 = StateGraph(SubGraphState)\n",
    "subgraph_builder_1.add_node(\"subgraph_node_1\", subgraph_node_1)\n",
    "subgraph_builder_1.add_edge(START, \"subgraph_node_1\")\n",
    "subgraph_builder_1.add_edge(\"subgraph_node_1\", END)\n",
    "subgraph_1 = subgraph_builder_1.compile(checkpointer=False)  # Disable checkpointing\n",
    "\n",
    "# Build the second subgraph\n",
    "subgraph_builder_2 = StateGraph(SubGraphState)\n",
    "subgraph_builder_2.add_node(\"subgraph_node_2\", subgraph_node_2)\n",
    "subgraph_builder_2.add_edge(START, \"subgraph_node_2\")\n",
    "subgraph_builder_2.add_edge(\"subgraph_node_2\", END)\n",
    "subgraph_2 = subgraph_builder_2.compile(checkpointer=False)  # Disable checkpointing\n",
    "\n",
    "# Define the state structure for the main graph\n",
    "class MainGraphState(TypedDict):\n",
    "    value: int\n",
    "    result: int\n",
    "\n",
    "# Define the main graph node\n",
    "def main_node(state: MainGraphState):\n",
    "    subgraph_output_1 = subgraph_1.invoke({\"value\": state[\"value\"]})\n",
    "    subgraph_output_2 = subgraph_2.invoke({\"value\": state[\"value\"]})\n",
    "    return {\"result\": subgraph_output_1[\"value\"] + subgraph_output_2[\"value\"]}\n",
    "\n",
    "# Build the main graph\n",
    "main_builder = StateGraph(MainGraphState)\n",
    "main_builder.add_node(\"main_node\", main_node)\n",
    "main_builder.add_edge(START, \"main_node\")\n",
    "main_builder.add_edge(\"main_node\", END)\n",
    "\n",
    "# Compile the main graph\n",
    "main_graph = main_builder.compile(checkpointer=MemorySaver())\n",
    "\n",
    "# Config\n",
    "config = {\n",
    "    \"configurable\": {\n",
    "        \"thread_id\": uuid.uuid4(),  # Unique thread identifier for execution\n",
    "    }\n",
    "}\n",
    "\n",
    "try:\n",
    "    result = main_graph.invoke({\"value\": 5, \"result\": 0}, config)\n",
    "except MultipleSubgraphsError as e:\n",
    "    print(f\"MultipleSubgraphsError: {e}\")\n",
    "print(\"Execution succeeded:\", result)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain-opentutorial-99wpaVyw-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
